package com.example.lots_of_demo.security;

import com.example.lots_of_demo.filter.JwtAuthenticationTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @author : LZJ
 * @description : code for LZJ
 * @date : 2021/2/11
 */
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private final MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;  // 自定义登录成功处理
    private final MyAuthenticationFailureHandler myAuthenticationFailureHandler;  // 自定义登录失败处理
    private final MyRestfulAccessDeniedHandler myRestfulAccessDeniedHandler;      //自定义未授权登录处理
    private final MyRestAuthenticationEntryPoint myRestAuthenticationEntryPoint;      //自定义未登录处理

    @Autowired
    public WebSecurityConfig(MyAuthenticationSuccessHandler myAuthenticationSuccessHandler, MyAuthenticationFailureHandler myAuthenticationFailureHandler, MyRestfulAccessDeniedHandler myRestfulAccessDeniedHandler, MyRestAuthenticationEntryPoint myRestAuthenticationEntryPoint) {
        this.myAuthenticationSuccessHandler = myAuthenticationSuccessHandler;
        this.myAuthenticationFailureHandler = myAuthenticationFailureHandler;
        this.myRestfulAccessDeniedHandler = myRestfulAccessDeniedHandler;
        this.myRestAuthenticationEntryPoint = myRestAuthenticationEntryPoint;
    }

    //spring-security5.X版本后必须啊哟解码器，否则报错
    @Bean
    public PasswordEncoder passwordEncoder() {
        return MyPasswordEncoder.getInstance();
    }

    //安全拦截机制
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .formLogin()//表单登录
                .loginProcessingUrl("/user/login")//登录处理URL
                .usernameParameter("username")//指定表单用户参数名
                .passwordParameter("password")//指定表单用户密码参数名
                .successHandler(myAuthenticationSuccessHandler)//登录成功处理器
                .failureHandler(myAuthenticationFailureHandler)//登录失败处理器
                .permitAll()
                .and()
                .logout().logoutUrl("/logout")//登出默认api
                .and()
                .authorizeRequests()
                .anyRequest().authenticated()//任何请求都要认证
                .and()
                .csrf()
                .disable()
                .sessionManagement()// 基于token，所以不需要session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and();

        //禁用浏览器缓存
        http.headers().cacheControl();
        // 添加JWT filter
        http.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
        //添加自定义未授权和未登录结果返回
        http.exceptionHandling()
                .accessDeniedHandler(myRestfulAccessDeniedHandler)
                .authenticationEntryPoint(myRestAuthenticationEntryPoint);
    }

    @Bean
    JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter(){
        return new JwtAuthenticationTokenFilter();
    }

}
